﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace BreukenRekenmachine.Model
{
    delegate Breuk DelegateBreukenBewerking(Breuk b1, Breuk b2);
    class ProgrammeerbareBreukContainer : BreukContainer
    {
        String[] volgorde;
        public ProgrammeerbareBreukContainer(String[] volgorde)
        {
            this.volgorde = volgorde;

        }
        public ProgrammeerbareBreukContainer()
        {
        }



        /// <summary>
        /// Doet de bewerking, aangeduid door delegateBreukenBewerking op de hele breukenlijst.
        /// </summary>
        /// <param name="delegateBreukenBewerking">De bewerking</param>
        /// <returns>Het resultaat</returns>
        public Breuk doeBewerking(DelegateBreukenBewerking delegateBreukenBewerking)
        {
            Breuk temp = null;
            if (breuken.Count > 0)
            {
                temp = new Breuk(breuken[0].Teller, breuken[0].Noemer);
                for (int i = 1; i < breuken.Count; i++)
                {
                    temp = delegateBreukenBewerking(temp, Breuken[i]);
                }
            }
            return temp;

        }
        /// <summary>
        /// Doet de bewerking, aangeduid door delegateBreukenBewerking op de hele breukenlijst.
        /// Indien de lijst te klein is, beginnen we van voren af aan.
        /// </summary>
        /// <param name="delegateBreukenBewerking">De bewerking</param>
        /// <param name="aantal">Hoeveel bewerkingen</param>
        /// <returns></returns>
        public Breuk doeBewerking(DelegateBreukenBewerking delegateBreukenBewerking, int aantal)
        {
            while (aantal > breuken.Count)
            {
                breuken.AddRange(breuken.GetRange(0, breuken.Count));
            }
            breuken.RemoveRange(aantal, breuken.Count - aantal);
            Breuk temp = null;
            if (breuken.Count > 0)
            {
                temp = new Breuk(breuken[0].Teller, breuken[0].Noemer);
                for (int i = 1; i < breuken.Count; i++)
                {
                    temp = delegateBreukenBewerking(temp, Breuken[i]);
                }
            }
            return temp;

        }
        public String doeBewerking(DelegateBreukenBewerking[] delegateBreukenBewerkingen, String[] operanden)
        {
            String output = "";
            int i = 0;
            Breuk temp = new Breuk(breuken[0].Teller, breuken[0].Noemer);
            output = output + temp.ToString() + " " + operanden[0] + " ";
            foreach (DelegateBreukenBewerking d in delegateBreukenBewerkingen)
            {
                i++;
                output = output + Breuken[i].ToString();

                if (!(i >= operanden.Length))
                {
                    output = output + " " + operanden[i] + " ";
                }
                temp = d(temp, Breuken[i]);
            }
            temp.Vereenvoudig();
            output = output + "= " + temp.ToString();

            return output;
        }
        public String doeBewerkingMetVolgorde(DelegateBreukenBewerking[] delegateBreukenBewerkingen, String[] operanden, String[] volgordes)
        {
            int volgorde = 0;
            String last = "";
            List<int> gebruikt = new List<int>();
            String output = "";
            ArrayList volgordeslist = new ArrayList(volgordes);
            ArrayList operandenlist = new ArrayList(operanden);
            ArrayList breukenlist = new ArrayList(Breuken);

            System.Console.WriteLine("pre");
            foreach (String s in volgordeslist)//bewerkingen volgorde afgaan
            {
                foreach (String op in operandenlist)//de opgave overlopen
                {

                    if (s == op && !(gebruikt.Contains(volgorde))&&(volgorde+1)<breukenlist.ToArray().Length)//een bewerking gevonden
                    {
                        last = s;
                        System.Console.WriteLine(op);
                        output = output + "\n(" + (String)breukenlist[volgorde].ToString() + " " + operandenlist[volgorde] + " " + (String)breukenlist[volgorde + 1].ToString() + ")";
                        breukenlist[volgorde] = delegateBreukenBewerkingen[volgorde]((Breuk)breukenlist[volgorde], (Breuk)breukenlist[volgorde + 1]);



                        breukenlist.RemoveAt(volgorde + 1);
                        gebruikt.Add(volgorde);
                        System.Console.WriteLine("gebruikt:"+volgorde);
                        System.Console.WriteLine("lengte:"+breukenlist.ToArray().Length);

                    }
                    System.Console.WriteLine("was :" + volgorde);
                    volgorde++;
                }
                volgorde = 0;
            }

            Breuk temp = (Breuk)breukenlist[0];
            temp.Vereenvoudig();
            output = output + "= " + temp.ToString();
            //Breuken = breukenlist;
            return output;
        }

        //public String doeBewerkingMetVolgorde(DelegateBreukenBewerking[] delegateBreukenBewerkingen, String[] operanden, String[] volgordes)
        //{
        //    int volgorde = 0;
        //    List<int> gebruikt= new List<int>();
        //    String output = "";
        //    ArrayList volgordeslist = new ArrayList(volgordes);
        //    ArrayList operandenlist = new ArrayList(operanden);
        //    ArrayList breukenlist = new ArrayList(Breuken);

        //    System.Console.WriteLine("pre");
        //    foreach (String s in volgordeslist)//bewerkingen volgorde afgaan
        //    {
        //        foreach (String op in operandenlist)//de opgave overlopen
        //        {
                    
        //            if (s == op&&!(gebruikt.Contains(volgorde)))//een bewerking gevonden
        //            {
        //                System.Console.WriteLine(op);
        //                output = output +"\n("+(String)breukenlist[volgorde].ToString()+ " " + operandenlist[volgorde] + " "+(String)breukenlist[volgorde + 1].ToString()+")";
        //                breukenlist[volgorde] = delegateBreukenBewerkingen[volgorde]((Breuk)breukenlist[volgorde], (Breuk)breukenlist[volgorde + 1]);
                        

                        
        //                breukenlist.RemoveAt(volgorde + 1);
        //                gebruikt.Add(volgorde);
        //                System.Console.WriteLine(breukenlist.ToArray().Length);

        //            }
        //            volgorde++;
        //        }
        //        volgorde = 0;
        //    }

        //    Breuk temp = (Breuk)breukenlist[0];
        //    temp.Vereenvoudig();
        //    output = output + "= " + temp.ToString();
        //    //Breuken = breukenlist;
        //    return output;
        //}

        public override String ToString()
        {
            StringBuilder uitvoer = new StringBuilder("\nLijst van de huidige breuken:\n");
            uitvoer.Append("\n\nVan klein naar groot: ");
            breuken.Sort(delegate(Breuk b1, Breuk b2) { return b1.CompareTo(b2); });
            breuken.ForEach(delegate(Breuk b) { uitvoer.Append(String.Format("{0}/{1} ", b.Teller, b.Noemer)); });

            uitvoer.Append("\nVan groot naar klein: ");
            breuken.Sort(delegate(Breuk b1, Breuk b2) { return b2.CompareTo(b1); });
            breuken.ForEach(delegate(Breuk b) { uitvoer.Append(String.Format("{0}/{1} ", b.Teller, b.Noemer)); });
            return uitvoer.ToString();
        }
    }
}
